library(dplyr)
library(readr)
library(sf)
library(ggplot2)
library(geobr)
library(stringr)
library(viridis)
library(leaflet)
library(scales)
library(here)
library(DT)
# Definição da estrutura de pastas para organizar os dados
pasta_base <- here("data")
pasta_out <- sprintf("%s/03_indicators", pasta_base)
pasta_shapes <- sprintf("%s/04_shapes", pasta_base)
cn22dom_vars <- read_csv(
file.path(pasta_out, "cn22dom_vars.csv"),
show_col_types = FALSE
)
# glimpse(cn22dom_vars)Mapas - São Paulo/SP
Indicadores domiciliares por setor censitário
Mapas de Indicadores
Código IBGE do município: 3550308
Ano de referência: 2022
Fonte: IBGE - Censo Demográfico 2022
Este documento gera mapas interativos dos indicadores domiciliares do Censo 2022 para o município de São Paulo. Os dados são visualizados por setor censitário, permitindo análises detalhadas intraurbanas.
1. Configuração do Ambiente
# Definição do município
cod_mun <- "3550308"
nome_mun <- "São Paulo"
stopifnot(cod_mun %in% cn22dom_vars$cod_municipio)
# Preparar base de indicadores
indicadores <- cn22dom_vars %>%
mutate(
cod_setor = as.character(cod_setor),
cod_municipio = as.character(cod_municipio)
)
cat(
"Indicadores carregados (absolutos e relativos): ",
nrow(indicadores),
" setores\n",
sep = ""
)Indicadores carregados (absolutos e relativos): 468099 setores
# Filtrar para o município
indicadores_mun <- indicadores %>%
filter(cod_municipio == cod_mun) %>%
mutate(cod_setor_ibge = cod_setor)
cat(
"Setores em ",
nome_mun,
": ",
nrow(indicadores_mun),
"\n\n",
sep = ""
)Setores em São Paulo: 27301
# Verificação final
if (nrow(indicadores_mun) == 0) {
stop("Nenhum setor encontrado para ", nome_mun)
}
cat("Primeiro setor: ", indicadores_mun$cod_setor[1], "\n", sep = "")Primeiro setor: 355030801000001
cat("Exemplo de indicador disponível:\n")Exemplo de indicador disponível:
vars_cn22 <- names(indicadores_mun)[str_detect(names(indicadores_mun), "^cn22_")]
print(head(vars_cn22, 1))[1] "cn22_dom01_ocu_tot_1"
2. Baixar e Preparar Shapes dos Setores Censitários
# Nome do arquivo shape para este município
shape_file <- file.path(pasta_shapes, paste0("setores_", cod_mun, ".gpkg"))
if (!file.exists(shape_file)) {
cat("Baixando shapes dos setores censitários...\n")
# URL base dos shapes do IBGE (BC250 - versão mais recente)
# Para 2022, usar a base de 2019 que é compatível
base_url <- "https://geoftp.ibge.gov.br/cartas_e_mapas/bases_cartograficas_continuas/bc250/versao2023/geopackage/"
# Determinar UF a partir do código do município
uf_code <- substr(cod_mun, 1, 2)
# Mapeamento código UF para sigla
uf_siglas <- c(
"11" = "RO", "12" = "AC", "13" = "AM", "14" = "RR", "15" = "PA",
"16" = "AP", "17" = "TO", "21" = "MA", "22" = "PI", "23" = "CE",
"24" = "RN", "25" = "PB", "26" = "PE", "27" = "AL", "28" = "SE",
"29" = "BA", "31" = "MG", "32" = "ES", "33" = "RJ", "35" = "SP",
"41" = "PR", "42" = "SC", "43" = "RS", "50" = "MS", "51" = "MT",
"52" = "GO", "53" = "DF"
)
uf_sigla <- uf_siglas[uf_code]
if (is.na(uf_sigla)) {
stop("Código UF inválido: ", uf_code)
}
# URL alternativa: usar geobr para download simplificado
cat("Usando pacote geobr para download dos shapes...\n")
# Instalar geobr se necessário
if (!requireNamespace("geobr", quietly = TRUE)) {
install.packages("geobr")
}
library(geobr)
# Baixar shapes dos setores censitários
tryCatch({
setores_sf <- read_census_tract(
year = 2019, # Último ano disponível compatível com 2022
code_tract = "all",
simplified = TRUE
)
# Filtrar para o município
setores_mun <- setores_sf %>%
filter(code_muni == as.numeric(cod_mun))
# Salvar em arquivo local para cache
st_write(setores_mun, shape_file, quiet = TRUE)
cat("Shapes salvos em:", shape_file, "\n")
}, error = function(e) {
cat("Erro ao baixar via geobr:", e$message, "\n")
cat("Usando shapes locais se disponíveis...\n")
})
}
# Carregar shapes
if (file.exists(shape_file)) {
setores_sf <- st_read(shape_file, quiet = TRUE)
} else {
# Fallback: criar geometria simplificada a partir dos centroides
cat("Criando geometria aproximada a partir de coordenadas...\n")
# Se você tiver coordenadas dos setores, carregue aqui
# Por enquanto, criamos pontos aleatórios para demonstração
set.seed(123)
setores_sf <- indicadores_mun %>%
mutate(
geometry = st_sfc(
lapply(1:n(), function(i) {
# Coordenadas aproximadas do município
# Em produção, use coordenadas reais!
lon <- -46.6 + runif(1, -0.2, 0.2)
lat <- -23.5 + runif(1, -0.2, 0.2)
st_point(c(lon, lat))
})
)
) %>%
st_as_sf()
}
cat("Shapes carregados:", nrow(setores_sf), "setores\n")Shapes carregados: 27149 setores
3. Juntar Dados e Geometrias
# Converter código do setor para formato compatível
setores_com_dados <- setores_sf %>%
mutate(
code_tract_char = as.character(code_tract)
) %>%
left_join(
indicadores_mun,
by = c("code_tract_char" = "cod_setor_ibge")
)
# Verificar junção
setores_com_info <- setores_com_dados %>%
filter(!is.na(cn22_dom03_cas_tot_2))
cat("Setores com dados e geometria:", nrow(setores_com_info),
"(", round(nrow(setores_com_info)/nrow(indicadores_mun)*100, 1), "%)\n")Setores com dados e geometria: 24908 ( 91.2 %)
4. Mapa interativo 1: Proporção de casas x apartamentos
# Preparar dados para o mapa
dados_mapa <- setores_com_info %>%
mutate(
prop_casas = cn22_dom03_cas_tot_2 * 100,
prop_aptos = cn22_dom03_apt_tot_2 * 100,
densidade = cn22_dom03_6mor_tot_2 * 100
)
# Função para criar paleta de cores
criar_paleta <- function(variavel, cores = "YlOrRd", reversa = FALSE) {
colorNumeric(
palette = cores,
domain = variavel,
na.color = "#808080",
reverse = reversa
)
}
# Paleta para proporção de casas
pal_casas <- criar_paleta(dados_mapa$prop_casas, "YlOrRd")
# Criar mapa Leaflet
mapa_casas <- leaflet(dados_mapa) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(
fillColor = ~pal_casas(prop_casas),
fillOpacity = 0.7,
color = "#444444",
weight = 0.5,
smoothFactor = 0.5,
label = ~paste(
"Setor:", code_tract_char,
"<br>Casas:", round(prop_casas, 1), "%",
"<br>Aptos:", round(prop_aptos, 1), "%",
"<br>Densidade (>6 moradores):", round(densidade, 1), "%"
) %>% lapply(htmltools::HTML),
highlightOptions = highlightOptions(
weight = 2,
color = "#666666",
bringToFront = TRUE
)
) %>%
addLegend(
pal = pal_casas,
values = ~prop_casas,
opacity = 0.7,
title = "% de Casas",
position = "bottomright",
labFormat = labelFormat(suffix = "%")
) %>%
addControl(
paste(nome_mun, "- Proporção de Domicílios tipo Casa"),
position = "topright"
)
mapa_casas5. Mapa interativo 2: Domicílios improvisados
# Filtrar setores com dados de improvisados
dados_improvisados <- dados_mapa %>%
mutate(
prop_improvisados = cn22_dom02_dpio_tot_2 * 100
) %>%
filter(!is.na(prop_improvisados) & prop_improvisados > 0)
# Paleta para improvisados (vermelho = mais crítico)
pal_improvisados <- criar_paleta(dados_improvisados$prop_improvisados, "Reds")
# Criar mapa
mapa_improvisados <- leaflet(dados_improvisados) %>%
addProviderTiles("CartoDB.DarkMatter") %>%
addPolygons(
fillColor = ~pal_improvisados(prop_improvisados),
fillOpacity = 0.8,
color = "#222222",
weight = 0.3,
label = ~paste(
"Setor:", code_tract_char,
"<br>Domic. improvisados:", round(prop_improvisados, 2), "%",
"<br>Total domicílios:", cn22_dom01_ocu_tot_1
) %>% lapply(htmltools::HTML)
) %>%
addLegend(
pal = pal_improvisados,
values = ~prop_improvisados,
opacity = 0.8,
title = "% Improvisados",
position = "bottomright",
labFormat = labelFormat(suffix = "%", digits = 2)
) %>%
addControl(
paste(nome_mun, "- Domicílios Improvisados"),
position = "topright"
)
mapa_improvisados6. Mapas Estáticos para Exportação
# Criar mapas estáticos com ggplot2
if (all(st_geometry_type(dados_mapa) %in% c("POLYGON", "MULTIPOLYGON"))) {
# Mapa 1: Proporção de casas
mapa_estatico1 <- ggplot(dados_mapa) +
geom_sf(aes(fill = prop_casas), color = NA, size = 0.1) +
scale_fill_viridis(
name = "% Casas",
option = "plasma",
na.value = "gray90",
labels = scales::percent_format(scale = 1)
) +
labs(
title = paste("Proporção de Domicílios tipo Casa -", nome_mun),
subtitle = "Por setor censitário - Censo 2022",
caption = "Fonte: IBGE - Censo Demográfico 2022"
) +
theme_void() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "bottom",
legend.key.width = unit(2, "cm")
)
print(mapa_estatico1)
# Mapa 2: Domicílios improvisados
if (nrow(dados_improvisados) > 0) {
mapa_estatico2 <- ggplot(dados_improvisados) +
geom_sf(aes(fill = prop_improvisados), color = NA, size = 0.1) +
scale_fill_gradientn(
name = "% Improvisados",
colors = c("lightyellow", "orange", "red", "darkred"),
na.value = "gray90",
limits = c(0, max(dados_improvisados$prop_improvisados, na.rm = TRUE)),
labels = scales::percent_format(scale = 1, accuracy = 0.1)
) +
labs(
title = paste("Domicílios Improvisados -", nome_mun),
subtitle = "Por setor censitário - Censo 2022",
caption = "Fonte: IBGE - Censo Demográfico 2022"
) +
theme_void() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "bottom",
legend.key.width = unit(2, "cm")
)
print(mapa_estatico2)
}
}

7. Análise por Bairro/Distrito
# Agregar indicadores por bairro (se disponível)
if ("nome_bairro" %in% names(indicadores_mun)) {
bairros_agg <- indicadores_mun %>%
group_by(cod_bairro, nome_bairro) %>%
summarise(
n_setores = n(),
media_casas = mean(cn22_dom03_cas_tot_2 * 100, na.rm = TRUE),
media_aptos = mean(cn22_dom03_apt_tot_2 * 100, na.rm = TRUE),
media_improvisados = mean(cn22_dom02_dpio_tot_2 * 100, na.rm = TRUE),
media_densidade = mean(cn22_dom03_6mor_tot_2 * 100, na.rm = TRUE),
.groups = 'drop'
) %>%
arrange(desc(media_improvisados))
# Gráfico de ranking
top_bairros <- bairros_agg %>%
filter(!is.na(nome_bairro) & nome_bairro != "") %>%
arrange(desc(media_improvisados)) %>%
head(15)
if (nrow(top_bairros) > 0) {
ggplot(top_bairros,
aes(x = reorder(nome_bairro, media_improvisados),
y = media_improvisados)) +
geom_col(fill = "steelblue", alpha = 0.8) +
geom_text(aes(label = round(media_improvisados, 2)),
hjust = -0.2, size = 3) +
coord_flip() +
labs(
title = paste("Top 15 Bairros com Mais Domicílios Improvisados -", nome_mun),
x = "Bairro",
y = "% de Domicílios Improvisados"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold"),
axis.text.y = element_text(size = 9)
)
}
}8. Tabela Interativa de Indicadores
# Criar tabela resumo para os primeiros 50 setores
tabela_resumo <- setores_com_info %>%
st_drop_geometry() %>%
select(
Setor = code_tract_char,
Bairro = nome_bairro,
`Casas (%)` = cn22_dom03_cas_tot_2,
`Aptos (%)` = cn22_dom03_apt_tot_2,
`Improvisados (%)` = cn22_dom02_dpio_tot_2,
`>6 Moradores (%)` = cn22_dom03_6mor_tot_2,
`Total Domicílios` = cn22_dom01_ocu_tot_1
) %>%
mutate(
across(where(is.numeric) & contains("%"), ~ round(.x * 100, 2)),
across(where(is.numeric) & !contains("%"), ~ round(.x, 0))
) %>%
head(50) # Limitar para performance
# Tabela interativa com DT
datatable(
tabela_resumo,
options = list(
pageLength = 10,
dom = 'Bfrtip',
buttons = c('copy', 'csv', 'excel'),
scrollX = TRUE
),
caption = paste("Indicadores Domiciliares - Primeiros 50 Setores -", nome_mun),
rownames = FALSE,
filter = 'top'
) %>%
formatStyle(
'Improvisados (%)',
background = styleColorBar(tabela_resumo$`Improvisados (%)`, 'lightcoral'),
backgroundSize = '100% 90%',
backgroundRepeat = 'no-repeat'
) %>%
formatStyle(
'Casas (%)',
background = styleColorBar(tabela_resumo$`Casas (%)`, 'lightblue'),
backgroundSize = '100% 90%'
)9. Resumo Estatístico
# Calcular estatísticas descritivas
resumo_estatistico <- indicadores_mun %>%
summarise(
`Total Setores` = n(),
`Média Casas (%)` = mean(cn22_dom03_cas_tot_2 * 100, na.rm = TRUE),
`Média Aptos (%)` = mean(cn22_dom03_apt_tot_2 * 100, na.rm = TRUE),
`Média Improvisados (%)` = mean(cn22_dom02_dpio_tot_2 * 100, na.rm = TRUE),
`Média >6 Moradores (%)` = mean(cn22_dom03_6mor_tot_2 * 100, na.rm = TRUE),
`Total Domicílios` = sum(cn22_dom01_ocu_tot_1, na.rm = TRUE),
`Total Moradores` = sum(cn22_dom01_ocu_tot_mor_1, na.rm = TRUE)
) %>%
mutate(across(where(is.numeric), ~ round(.x, 2)))
cat("RESUMO ESTATÍSTICO -", nome_mun, "\n")RESUMO ESTATÍSTICO - São Paulo
cat("================================\n")================================
print(resumo_estatistico)# A tibble: 1 × 7
`Total Setores` `Média Casas (%)` `Média Aptos (%)` `Média Improvisados (%)`
<dbl> <dbl> <dbl> <dbl>
1 27301 63.6 35.4 0.14
# ℹ 3 more variables: `Média >6 Moradores (%)` <dbl>, `Total Domicílios` <dbl>,
# `Total Moradores` <dbl>
10. Como Usar para Outros Municípios
Para gerar mapas para outro município, renderize com parâmetros diferentes:
# Rio de Janeiro
quarto render 03-mapa-cidades.qmd -P cod_mun:3304557 -P nome_mun:"Rio de Janeiro"
# Belo Horizonte
quarto render 03-mapa-cidades.qmd -P cod_mun:3106200 -P nome_mun:"Belo Horizonte"
# Curitiba
quarto render 03-mapa-cidades.qmd -P cod_mun:4106902 -P nome_mun:"Curitiba"Próximos passos: 1. Execute 01-import-data.qmd para baixar os dados 2. Execute 02-gerar-indicadores.qmd para calcular indicadores
3. Execute este documento para gerar os mapas 4. Para publicar: quarto render e suba a pasta docs/ para GitHub Pages
Documento gerado em 07/01/2026 19:31